const city = require('../constant/city');
const fields = require('../constant/fields');

/**
 * 验证身份证合法性
 * @param {string} cardId  身份证号码  String类型
 * @returns  {boolean} true合法,false不合法
 */
function checkTheIdCard(cardId) {
    // 检测身份证是否合法
    return !!(
        isCardNo(cardId) &&
        checkProvince(cardId) &&
        checkBirthday(cardId) &&
        checkParity(cardId)
    );
}

// 检查基本输入规则
function isCardNo(cardId) {
    const reg = /(^\d{17}(\d|X|x)$)/;
    return reg.test(cardId);
}

// 检测前两位是否为省份
function checkProvince(cardId) {
    const province = cardId.substr(0, 2);
    return Boolean(city[province]);
}

// 检测生日是否正确
function checkBirthday(cardId) {
    const reg = /^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X|x)$/;
    const matches = cardId.match(reg);
    const year = matches[2];
    const month = matches[3];
    const day = matches[4];
    // const birthday = new Date(`${year}/${month}/${day}`);
    return verifyBirthday(year, month, day);
}

// 检测日期
function verifyBirthday(year, month, day) {
    const now = new Date();
    const nowYear = now.getFullYear();
    const nowMonth = now.getMonth() + 1;
    const nowDay = now.getDate();
    // 判断年月日是否合理
    if (year < nowYear) {
        return true;
    } else if (year === nowYear && month < nowMonth) {
        return true;
    } else if (month === nowMonth && nowDay <= day) {
        return true;
    }
    return false;
}

// 检测检验位是否正确
function checkParity(cardId) {
    const arrInt = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
    const arrCh = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
    let cardTemp = 0;
    let i;
    let checkDigit;
    for (i = 0; i < 17; i++) {
        cardTemp += cardId.substr(i, 1) * arrInt[i];
    }
    checkDigit = arrCh[cardTemp % 11];
    console.log('身份证检验位应该是: ', checkDigit);
    return checkDigit == cardId.substr(17, 1);
}

/**
 * 校验手机号码
 * @param {string} phone 手机号码
 * @returns  {boolean} true合法,false不合法
 */
function checkThePhone(phone) {
    return /^1[3456789]\d{9}$/.test(phone);
}

/**
 * 校验用户名
 * @param {string} username 用户名
 * @returns  {boolean} true合法,false不合法
 */
function checkTheUsername(username) {
    return /^\w{6,32}$/.test(username);
}

/**
 * 校验用户密码
 * @param {string} password 用户密码
 * @returns  {boolean} true合法,false不合法
 */
function checkThePassword(password) {
    return /(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]){6,32}/.test(password);
}

/**
 * 校验邮箱
 * 邮箱规则
 * 1.邮箱以a-z、A-Z、0-9开头，最小长度为1.
 * 2.如果左侧部分包含-、_、.则这些特殊符号的前面必须包一位数字或字母。
 * 3.@ 符号是必填项
 * 4.右则部分可分为两部分，第一部分为邮件提供商域名地址，第二部分为域名后缀，现已知的最短为2位。最长的为6为。
 * 5.邮件提供商域可以包含特殊字符-、_、.
 * @param {string} email 邮箱
 * @returns  {boolean} true合法,false不合法
 */
function checkTheEmail(email) {
    return /^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/.test(
        email
    );
}

/**
 * 验证参数是否正确
 */
function validateField(obj) {
    const error = new Error();
    error.status = 400;
    const keys = Object.keys(obj);
    keys.forEach(key => {
        if (obj[key] === '') {
            error.message = `${fields[key]}不能为空`;
            throw error;
        }
    });
}


module.exports = {
    checkTheIdCard,
    checkThePhone,
    checkTheUsername,
    checkThePassword,
    checkTheEmail,
    validateField
};
